package com.xingkeduo.business.order.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xingkeduo.dto.*;
import com.xingkeduo.dto.param.ChannelType;
import com.xingkeduo.dto.param.PaymentParam;
import com.xingkeduo.dto.wxma.WxMaUserInfo;
import com.xingkeduo.remote.AdminRemoteService;
import com.xingkeduo.remote.feign.*;
import com.xingkeduo.utils.ResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.xingkeduo.utils.DateTimeUtils.HH_mm_ss;

/**
 * @author chi  2019-05-08 11:13
 **/
@Service
@Slf4j
public class WordPadService {

    @Resource
    private OrderFeignService orderFeignService;
    @Resource
    private WordPadFeignService wordPadFeignService;
    @Resource
    private StoreFeignService storeFeignService;
    @Resource
    private AdminRemoteService adminRemoateService;
    @Resource
    private AdminFeignService adminFeignService;
    @Resource
    private MarketingFeignService marketingFeignService;


    //weapp 小程序 wechat 微信公众号 alipay 支付宝生活号
    public PayResult pay(String f_user_id, String order_no, String mobile_type, String pa_flag) {

        ChannelType channelType = ChannelType.WECHAT_JSAPI;
        if ("weapp".equals(mobile_type)) {
            channelType = ChannelType.WECHAT_MINA;
        } else if ("wechat".equals(mobile_type)) {
            channelType = ChannelType.WECHAT_JSAPI;
        } else if ("alipay".equals(mobile_type)) {
            channelType = ChannelType.ALIPAY;
        }

        PaymentParam build = PaymentParam.builder()
                .userId(f_user_id)
                .orderNo(order_no)
                .channelType(channelType)
                .build();

        ResponseUtils responseUtils = orderFeignService.toPay(build);

        ResponseUtils<OrderDetailResponseDto> orderDetailResponseDtoResponseUtils = orderFeignService.queryByOrderNO(order_no);

        log.info("返回支付结果:{}", JSON.toJSONString(responseUtils));

        if (!responseUtils.success()) {

            if("9004".equals(responseUtils.getMsg())){
                PayResult payResult = new PayResult();
                payResult.setError(9004);
                payResult.setReason("用户信息更新中 请等待");
                payResult.setContent("");
                return payResult;
            }else {
                PayResult payResult = new PayResult();
                payResult.setError(1);
                payResult.setReason(responseUtils.getMsg());
                ContentBean contentBean = new ContentBean();
                contentBean.setOrder_no(order_no);
                contentBean.setOut_order_no("");

                if (orderDetailResponseDtoResponseUtils.success()) {
                    contentBean.setStore_id(orderDetailResponseDtoResponseUtils.getData().getStoreId());
                }

                contentBean.setJsApiParameters(null);
                payResult.setContent(contentBean);
                return payResult;

            }

        }

        PayResult payResult = new PayResult();
        payResult.setError(0);
        payResult.setReason(0);

        ContentBean contentBean = new ContentBean();
        contentBean.setOrder_no(order_no);

        if (orderDetailResponseDtoResponseUtils.success()) {
            contentBean.setStore_id(orderDetailResponseDtoResponseUtils.getData().getStoreId());
            BigDecimal payPrice = orderDetailResponseDtoResponseUtils.getData().getPayPrice();
            if (payPrice.equals(BigDecimal.ZERO)) {

                payResult.setContent(contentBean);
                return payResult;

            }
        }

        contentBean.setJsApiParameters(JSON.parseObject(JSON.toJSONString(responseUtils.getData())));
        if (ChannelType.ALIPAY.equals(channelType)) {
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(responseUtils.getData()));

            if (jsonObject != null) {
                contentBean.setOut_order_no(jsonObject.get("tradeNo").toString());

                JSONObject jsonObject1 = new JSONObject();

                jsonObject1.put("trade_no", jsonObject.get("tradeNo").toString());
                contentBean.setJsApiParameters(jsonObject1);
            }

        }

        payResult.setContent(contentBean);

        log.info("支付返回:{}", JSON.toJSONString(payResult));

        return payResult;

    }


    /**
     * 库存展示
     *
     * @param f_user_id
     * @param store_id
     * @param mobile_type
     * @param date
     * @param admin_id
     * @param service_type
     * @return
     */

    public PayResult time_appointment(Long f_user_id, Long store_id, String mobile_type, String date, Long admin_id, Integer service_type) {
        ResponseUtils<Map<String, StockVo>> staffStock = wordPadFeignService.getStaffStock(admin_id, store_id, date);

        log.info("调用 getStaffStock,请求值:adminId,{}  storeId,{}   date,{}", admin_id, store_id, date);
        log.info("调用 getStaffStock,返回值:{}", JSON.toJSONString(staffStock));

        if (staffStock.getStatus() != 1) {
            PayResult payResult = new PayResult();
            payResult.setError(1);
            payResult.setReason(staffStock.getMsg());
            return payResult;
        }

        //取前五个
        Map<String, StockVo> data = staffStock.getData();
        int i = 0;


        LinkedHashMap<String, StockVo> mapLimit5 = new LinkedHashMap<>();

        ArrayList<LocalDate> localDates = new ArrayList<>();

        for (String s : data.keySet()) {
            if (i < 5) {
                mapLimit5.put(s, data.get(s));
                localDates.add(LocalDate.parse("2019-" + s));
                i++;
            }
        }

        LocalDate start = localDates.stream().sorted().findFirst().get();
        LocalDate end = localDates.stream().sorted(Comparator.reverseOrder()).findFirst().get();

        /**
         * 活动优惠价格
         */
        ResponseUtils<Map<String, ActivityApiResponseVo>> mapResponseUtils = marketingFeignService.getBypassFlowActivityTime(store_id, admin_id, Long.valueOf(service_type), start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        log.info("调用 bindBagReceiveAccount,请求值:  storeId,{}  serviceType:{},  adminId:{},  start:{}, end:{}", store_id, service_type, admin_id, start.toString(), end.toString());
        log.info("调用 bindBagReceiveAccount,返回值:{}", JSON.toJSONString(mapResponseUtils));
        Map<String, ActivityApiResponseVo> data1 = mapResponseUtils.getData();

        /**
         * 库存基本价格
         */
        ResponseUtils<Map<String, PriceDto>> mapResponseEntity = orderFeignService.adminPrice(admin_id + "", store_id + "", service_type + "");
        log.info("调用 adminPrice,请求值:  storeId,{}  serviceType:{},  adminId:{}", store_id, service_type, admin_id);
        log.info("调用 adminPrice,返回值:{}", JSON.toJSONString(mapResponseEntity));


        Map<String, Object> mapDate = new LinkedHashMap<>();

        for (String value : mapLimit5.keySet()) {
            StockVo stockVo = mapLimit5.get(value);

            List<StaffStockVo> stockList = stockVo.getStockList();


            LinkedHashMap<String, Object> time_list = new LinkedHashMap<>();


            if (stockList != null && stockList.size() > 0) {
                int size = stockList.size();
                for (int a = 0; a < size; a++) {
                    StaffStockVo staffStockVo = stockList.get(a);

                    StockDto stockDto = new StockDto();
                    stockDto.setCan_appointment(staffStockVo.getStatus().equals((byte) 0) && (staffStockVo.getDisable() == null || !staffStockVo.getDisable()));

                    if (staffStockVo.getDisable() != null && staffStockVo.getDisable()) {
                        stockDto.setReason("时间已过");
                    } else if (staffStockVo.getStatus().equals(StockStatusEnum.SYSTEM_OCCUPY.getValue())) {
                        stockDto.setReason("发型师休息");
                    } else if (!stockDto.isCan_appointment()) {
                        stockDto.setReason("已被预约");
                    } else {
                        stockDto.setReason("空闲");
                    }

                    if (service_type == 4) {
                        StaffStockVo staffStockNext = null;
                        try {
                            staffStockNext = stockList.get(a + 1);
                        } catch (Exception e) {
                        }

                        if (staffStockNext == null) {
                            stockDto.setReason("已被预约");
                            stockDto.setCan_appointment(false);
                        } else {
                            StockDto stockDtoNext = new StockDto();
                            stockDtoNext.setCan_appointment(staffStockNext.getStatus().equals((byte) 0) && (staffStockNext.getDisable() == null || !staffStockNext.getDisable()));


                            boolean flag = true;
                            if (staffStockNext.getDisable() != null && staffStockNext.getDisable()) {
                                flag = false;
                            } else if (staffStockNext.getStatus().equals(StockStatusEnum.SYSTEM_OCCUPY.getValue())) {
                                flag = false;
                            } else if (!stockDtoNext.isCan_appointment()) {
                                flag = false;
                            }

                            if (!flag) {
                                stockDto.setReason("已被预约");
                                stockDto.setCan_appointment(false);
                            }
                        }

                    }

                    //stockDto.setReason(StockStatusEnum.getAttendanceType(staffStockVo.getStatus().intValue()).getDescription());
                    stockDto.setStartTime(staffStockVo.getStartTime());

                    Map<String, PriceDto> mapData = mapResponseEntity.getData();
                    PriceDto priceDto = mapData.get(admin_id + "");
                    if (priceDto != null) {

                        PriceBean priceBean = new PriceBean();
                        priceBean.setTotal_price(priceDto.getCurrPrice().toString());

                        ActivityApiResponseVo activityApiResponseVo = data1.get("2019-" + value);
                        LocalTime startTime = LocalTime.parse(staffStockVo.getStartTime());

                        if (activityApiResponseVo != null && activityApiResponseVo.getActivityDays() != null) {
                            List<ActivityDaysResponseVo> activityDays = activityApiResponseVo.getActivityDays();
                            activityDays.stream().filter(activityDaysResponseVo -> {
                                return startTime.compareTo(LocalTime.parse(activityDaysResponseVo.getEndTime(), HH_mm_ss)) <= 0 && startTime.compareTo(LocalTime.parse(activityDaysResponseVo.getStartTime(), HH_mm_ss)) >= 0;
                            }).findFirst().ifPresent(activityDaysResponseVo -> {

                                BigDecimal activityAmount = activityDaysResponseVo.getActivityAmount();
                                BigDecimal total = priceDto.getCurrPrice();


                                String s = total.subtract(activityAmount).compareTo(BigDecimal.ZERO) > 0 ? activityAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString() : total.setScale(2, BigDecimal.ROUND_HALF_UP).toString();

                                priceBean.setReduce_price(total.subtract(activityAmount).compareTo(BigDecimal.ZERO) > 0 ? activityAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString() : total.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                                priceBean.setActivity_id(activityApiResponseVo.getId() + "");
                                priceBean.setActivity_name(activityApiResponseVo.getName());
                                priceBean.setActivity_content(activityApiResponseVo.getSubTitle());
                                priceBean.setActivity_type(activityApiResponseVo.getActivityType());
                            });

                        }

                        priceBean.setReal_price(new BigDecimal(priceBean.getTotal_price()).subtract(new BigDecimal(priceBean.getReduce_price())).toString());


                        stockDto.setPrice(priceBean);
                    }

                    time_list.put(stockDto.getStartTime(), stockDto);
                }
            }


            HashMap<String, Object> map = new LinkedHashMap<>();
            map.put("time_list", time_list);
            map.put("date_detail", "2019-" + stockVo.getDate());
            map.put("date", stockVo.getDate());
            map.put("week", stockVo.getWeek());
            if (stockList == null || stockList.size() == 0) {
                map.put("reason", "发型师本日休息");
            } else {
                map.put("reason", "");
            }

            //暂时不需要
            map.put("min_real_price", "");

            mapDate.put("2019-" + stockVo.getDate(), map);
        }

        HashMap<String, Object> map1 = new HashMap<>();
        map1.put("cache_list", mapDate);

        PayResult payResult = new PayResult();
        payResult.setError(0);
        payResult.setReason(0);
        payResult.setContent(map1);

        log.info("time_appointment response:{}", JSON.toJSONString(payResult));

        return payResult;


    }


    public PayResult get_admin_list(Long f_user_id, Long store_id, String mobile_type, Integer service_type) {
        PayResult payResult = new PayResult();
        if (null == f_user_id || f_user_id.longValue() <= 0L) {
            payResult = payResult.returnErrorUserAuth("用户不存在");
            payResult.setContent("用户不存在");
            return payResult;
        }
        if (f_user_id != null && f_user_id > 0L) {
            ResponseUtils<Long> responseUtils = adminFeignService.checkUserExist(f_user_id, mobile_type);
            if (!responseUtils.success()) {
                payResult = payResult.returnErrorUserAuth("用户不存在");
                payResult.setContent("用户不存在");
                return payResult;
            }
        }

        HashMap<Object, Object> returnMap = new HashMap<>();

        if (service_type != null && service_type == 4) {

            ResponseUtils<List<ChooseHairstyleDTO>> listResponseUtils = storeFeignService.hairstyleList("4");

            log.info("hairstyleList:{}", JSON.toJSONString(listResponseUtils));
            if (listResponseUtils.success()) {

                List<ChooseHairstyleDTO> data = listResponseUtils.getData();

                List<HashMap<String, Object>> collect = data.stream().map(chooseHairstyleDTO -> {

                    HashMap<String, Object> map = new HashMap<>();
                    map.put("id", chooseHairstyleDTO.getId());
                    map.put("name", chooseHairstyleDTO.getName());
                    map.put("pic", chooseHairstyleDTO.getCover());
                    map.put("is_new", true);
                    map.put("face_list", chooseHairstyleDTO.getFaceList().stream().collect(Collectors.joining(",")));
                    return map;
                }).collect(Collectors.toList());

                returnMap.put("hairstyle_list", collect);

            }
        }


        ResponseUtils<List<StockWorkTimeVo>> responseUtils = wordPadFeignService.getMinFreeStockByStoreId(store_id);
        log.info("调用 getMinFreeStockByStoreId,请求值storeId:{},返回值:{}", store_id, JSON.toJSONString(responseUtils));


        if (!responseUtils.success()) {
            return payResult.returnError("排班调用失败");
        }

        List<StockWorkTimeVo> data1 = responseUtils.getData();

        if (data1 == null || data1.size() == 0) {

            payResult = payResult.returnError("发型师为空");
            payResult.setContent(returnMap);
            return payResult;

        }


        List<Long> collect2 = data1.stream().map(StockWorkTimeVo::getStaffId).collect(Collectors.toList());
        ResponseUtils<List<BaseDTO>> serviceids = adminFeignService.serviceids(collect2);
        log.info("admin serviceids:param {}, response:{}", collect2, JSON.toJSONString(serviceids));

        if (serviceids.success()) {
            List<BaseDTO> data = serviceids.getData();

            data1 = data1.stream().filter(stockWorkTimeVo -> {
                long count = data.stream().filter(baseDTO -> {
                    return baseDTO.getCraftsmanId() == stockWorkTimeVo.getStaffId();
                }).filter(baseDTO -> {
                    return baseDTO.getServiceIds().contains(Long.valueOf(service_type));
                }).count();
                return count > 0;
            }).collect(Collectors.toList());

        }


        String adminIds = data1.stream().map(StockWorkTimeVo::getStaffId).map(String::valueOf).collect(Collectors.joining(","));


        ResponseUtils<Map<String, PriceDto>> mapResponseEntity = orderFeignService.adminPrice(adminIds, store_id + "", service_type + "");
        log.info("调用 adminPrice,请求值:  storeId,{}  serviceType:{},  adminId:{}", store_id, service_type, adminIds);
        log.info("调用 adminPrice,返回值:{}", JSON.toJSONString(mapResponseEntity));

        log.info("mapResponseEntity response:{}", JSON.toJSONString(mapResponseEntity.getData()));

        List<HairStoreDto> collect1 = data1.stream().map(s -> {

            String a = "";
            HairStoreDto build = new HairStoreDto();
            if (StringUtils.isNotBlank(s.getNearlyAppointmentDateFormat())) {

                LocalDate date = LocalDate.parse(s.getNearlyAppointmentDateFormat());
                if (date.compareTo(LocalDate.now()) == 0) {
                    a = "今天";
                } else if (date.minusDays(1L).compareTo(LocalDate.now()) == 0) {
                    a = "明天";
                } else {
                    a = date.getMonthValue() + "月" + date.getDayOfMonth() + "日";
                }

                build = HairStoreDto.builder()
                        .admin_id(s.getStaffId() + "")
                        .today_rest(s.getTodayRest())
                        .today_full(s.getTodayFull())
                        .nearly_appointment_date(a)
                        .nearly_appointment_date_format(s.getNearlyAppointmentDateFormat())
                        .nearly_appointment_time(s.getNearlyAppointmentTime())
                        .nearly_appointment_timestamp(s.getNearlyAppointmentTimestamp())

                        .build();

            } else {
                build = HairStoreDto.builder()
                        .admin_id(s.getStaffId() + "")
                        .today_rest(false)
                        .today_full(true)
                        .nearly_appointment_date(a)
                        .nearly_appointment_date_format("")
                        .nearly_appointment_time("")

                        .build();
            }

            AdminDetailDto adminDetailDto = adminRemoateService.craftsman_get(s.getStaffId() + "");
            if (adminDetailDto != null) {
                build.setName(adminDetailDto.getName() == null ? "" : adminDetailDto.getName());
                build.setMotto(adminDetailDto.getSignaTure());
                build.setAvatar(adminDetailDto.getPath());
            }

            if (mapResponseEntity.success()) {
                Map<String, PriceDto> data = mapResponseEntity.getData();
                PriceDto priceDto = data.get(s.getStaffId() + "");
                if (priceDto != null) {

                    String s1 = priceDto.getCurrPrice().stripTrailingZeros().toPlainString();
                    if (!s1.contains(".")) {
                        s1 = s1 + ".0";
                    }

                    String s2 = priceDto.getReducePrice().stripTrailingZeros().toPlainString();
                    if (!s2.contains(".")) {
                        s2 = s2 + ".0";
                    }

                    build.setCurr_price(s1);
                    build.setReduce_price(s2);
                    build.setActivity_id(priceDto.getActivityId());
                    build.setActivity_name(priceDto.getActivityName());
                    build.setActivity_content(priceDto.getActivityContent());
                    build.setActivity_type(priceDto.getActivityType());
                } else {
                    log.info("{}获取不到价格详情", s.getStaffId());
                }

            }

            log.info("build:{}", JSON.toJSONString(build));
            return build;
        }).collect(Collectors.toList());

        Optional<StockWorkTimeVo> stockWorkTimeVoOptional = data1.stream().filter(s -> {
            return s.getNearlyAppointmentTimestamp() != null;
        }).sorted(Comparator.comparing(StockWorkTimeVo::getNearlyAppointmentTimestamp)).findFirst();


        returnMap.put("admin_list", collect1);


        //barber 价格
        ResponseUtils<List<JSONObject>> barberPrice = storeFeignService.getBarberPrice(store_id + "");
        if (barberPrice.success()) {
            Object price = barberPrice.getData().stream().findFirst().map(jsonObject -> {
                return jsonObject.get("price");
            }).orElse(0);
            returnMap.put("all_price", price);
        } else {
            returnMap.put("all_price", 0);
        }
        if (stockWorkTimeVoOptional.isPresent()) {
            StockWorkTimeVo stockWorkTimeVo = stockWorkTimeVoOptional.get();
            returnMap.put("nearly_appointment_date", stockWorkTimeVo.getNearlyAppointmentDate());
            returnMap.put("nearly_appointment_time", stockWorkTimeVo.getNearlyAppointmentTime());
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", f_user_id);
        ResponseUtils<WxMaUserInfo> consumerInfo = adminFeignService.getConsumerInfo(JSON.toJSONString(jsonObject));
        log.info("{}查询用户返回:{}", f_user_id, JSON.toJSONString(consumerInfo));
        if (consumerInfo != null && consumerInfo.success()) {
            returnMap.put("have_mobile", StringUtils.isNotBlank(consumerInfo.getData().getPhone()));
        } else {
            returnMap.put("have_mobile", false);
        }

        payResult.setContent(returnMap);
        payResult.setError(0);

        return payResult;

    }


}
